/// <reference path="../devextreme/ts/jquery.d.ts" />

($ => {
  function init(container, splitterParams) {
    const panel1 = container.children[0];
    const panel2 = container.children[2];
    const splitter = container.children[1];
    const { orientation, panel1MinSize, panel2MinSize, splitterWidth } = splitterParams;
    let containerWidth = container.clientWidth - splitterWidth;
    let containerHeight = container.clientHeight - splitterWidth;
    let { panel1Size, panel2Size } = splitterParams;
    let mainPanel,
      mainPanelSize,
      mainPanelMinSize,
      secondPanel,
      secondPanelSize,
      secondPanelMinSize,
      splitSizeUnit;
    let initialized = false;
    panel1Size = !panel1Size && !panel2Size ? '50%' : panel1Size;
    if (panel1Size) {
      mainPanel = panel1;
      mainPanelSize = panel1Size;
      mainPanelMinSize = panel1MinSize;
      secondPanel = panel2;
      secondPanelMinSize = panel2MinSize;
    } else if (panel2Size) {
      mainPanel = panel2;
      mainPanelSize = panel2Size;
      mainPanelMinSize = panel2MinSize;
      secondPanel = panel1;
      secondPanel.style.overflow = 'auto';
      secondPanelMinSize = panel1MinSize;
    }
    const getSecondPanelSize = () => {
      if (orientation === 'h') {
        if (splitSizeUnit === 'pixel') {
          return `${containerHeight - parseFloat(mainPanelSize)}px`;
        } else if (splitSizeUnit === 'percent') {
          return `${100 - parseFloat(mainPanelSize)}%`;
        }
      } else {
        if (splitSizeUnit === 'pixel') {
          return `${containerWidth - parseFloat(mainPanelSize)}px`;
        } else if (splitSizeUnit === 'percent') {
          return `${100 - parseFloat(mainPanelSize)}%`;
        }
      }
    };
    const updatePanelSize = () => {
      let actualMainPanelSize;
      if (initialized) {
        const containerSizeValue = orientation === 'h' ? containerHeight : containerWidth;
        const mainPanelMinSizeValue = getSizePixelValue(containerSizeValue, mainPanelMinSize);
        const secondPanelMinSizeValue = getSizePixelValue(containerSizeValue, secondPanelMinSize);
        const secondPanelSizeValue = getSizePixelValue(containerSizeValue, secondPanelSize);
        let mainPanelSizeValue = getSizePixelValue(containerSizeValue, mainPanelSize);
        if (mainPanelMinSizeValue && mainPanelMinSizeValue > mainPanelSizeValue) {
          mainPanelSizeValue = mainPanelMinSizeValue;
        }
        if (secondPanelMinSizeValue && secondPanelMinSizeValue > secondPanelSizeValue) {
          mainPanelSizeValue = containerSizeValue - secondPanelMinSizeValue;
        }
        if (mainPanelMinSizeValue) {
          mainPanelSizeValue = Math.max(mainPanelMinSizeValue, mainPanelSizeValue);
        }
        if (splitSizeUnit === 'pixel') {
          mainPanelSize = `${mainPanelSizeValue}px`;
          actualMainPanelSize = mainPanelSize;
        } else if (splitSizeUnit === 'percent') {
          mainPanelSize = `${(mainPanelSizeValue / containerSizeValue) * 100}%`;
          actualMainPanelSize = `${(mainPanelSizeValue / (containerSizeValue + splitterWidth)) * 100}%`;
        }
      } else {
        actualMainPanelSize = `calc(${mainPanelSize} - ${splitterWidth}px / 2)`;
      }
      const actualSecondPanelSize = `calc(100% - ${splitterWidth}px - ${actualMainPanelSize})`;
      if (orientation === 'h') {
        mainPanel.style.height = actualMainPanelSize;
        secondPanel.style.height = actualSecondPanelSize;
      } else {
        mainPanel.style.width = actualMainPanelSize;
        secondPanel.style.width = actualSecondPanelSize;
      }
    };
    splitSizeUnit = getSizeUnit(mainPanelSize);
    secondPanelSize = getSecondPanelSize();
    updatePanelSize();
    splitter.onpointerdown = e => {
      containerWidth = container.clientWidth - splitterWidth;
      containerHeight = container.clientHeight - splitterWidth;
      splitter.onpointermove = e => {
        if (e.buttons !== 1) {
          splitter.onpointermove = null;
          splitter.releasePointerCapture(e.pointerId);
          return;
        }
        const mainPanelWidth = mainPanel.clientWidth;
        const mainPanelHeight = mainPanel.clientHeight;
        if (splitSizeUnit === 'pixel') {
          if (orientation === 'h') {
            if (mainPanel === panel1) {
              mainPanelSize = `${mainPanelHeight + e.movementY}px`;
            } else {
              mainPanelSize = `${mainPanelHeight - e.movementY}px`;
            }
          } else {
            if (mainPanel === panel1) {
              mainPanelSize = `${mainPanelWidth + e.movementX}px`;
            } else {
              mainPanelSize = `${mainPanelWidth - e.movementX}px`;
            }
          }
        } else if (splitSizeUnit === 'percent') {
          if (orientation === 'h') {
            if (mainPanel === panel1) {
              mainPanelSize = `${((mainPanelHeight + e.movementY) / containerHeight) * 100}%`;
            } else {
              mainPanelSize = `${((mainPanelHeight - e.movementY) / containerHeight) * 100}%`;
            }
          } else {
            if (mainPanel === panel1) {
              mainPanelSize = `${((mainPanelWidth + e.movementX) / containerWidth) * 100}%`;
            } else {
              mainPanelSize = `${((mainPanelWidth - e.movementX) / containerWidth) * 100}%`;
            }
          }
        }
        secondPanelSize = getSecondPanelSize();
        updatePanelSize();
      };
      splitter.setPointerCapture(e.pointerId);
    };
    splitter.onpointerup = e => {
      splitter.onpointermove = null;
      splitter.releasePointerCapture(e.pointerId);
      let size = mainPanelSize;
      if (splitSizeUnit === 'pixel') {
        size = `${parseFloat(size).toFixed()}px`;
      } else if (splitSizeUnit === 'percent') {
        size = `${parseFloat(size).toFixed(2)}%`;
      }
    };
    initialized = true;
  }

  function createPanel() {
    const panel = document.createElement('DIV');
    panel.className = 'splitter';
    return panel;
  }

  function createSplitter(splitterParams) {
    const panel = document.createElement('DIV');
    panel.className = 'splitter';
    panel.style.cursor = splitterParams.orientation === 'h' ? 'n-resize' : 'e-resize';
    if (splitterParams.orientation === 'h') {
      panel.style.height = `${splitterParams.splitterWidth}px`;
    } else {
      panel.style.width = `${splitterParams.splitterWidth}px`;
    }
    panel.style.backgroundColor = splitterParams.splitterColor;
    return panel;
  }

  function getSizePixelValue(containerPixelSize, size) {
    const sizeUnit = getSizeUnit(size);
    if (sizeUnit === 'pixel') {
      return parseFloat(size);
    } else if (sizeUnit === 'percent') {
      const value = parseFloat(size);
      return (value / 100) * containerPixelSize;
    }
  }

  function getSizeUnit(size) {
    if (size?.endsWith('%')) {
      return 'percent';
    } else if (size?.endsWith('px')) {
      return 'pixel';
    }
  }

  $.fn.splitter = function (options) {
    options = {
      orientation: 'v',
      panel1MinSize: '20px',
      panel2MinSize: '20px',
      splitterWidth: 4,
      splitterColor: '#EEEEEE',
      ...options,
    };
    const $this = $(this[0]);
    const panels = $this.children();
    if (panels.length === 2) {
      $this.addClass('splitter-container');
      $this.addClass(options.orientation === 'h' ? 'splitter-horizontal' : 'splitter-vertical');
      $this.append($(createPanel()).append(panels[0]));
      $this.append(createSplitter(options));
      $this.append($(createPanel()).append(panels[1]));
      init(this[0], options);
    }
    return $this;
  };
})(jQuery);
